home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Dev / misc / temgen.lha / Temgen / tg-0.11 / printf.c < prev    next >
C/C++ Source or Header  |  2002-12-18  |  7KB  |  234 lines

  1. #include "alloc.h"
  2. #include "generator.h"
  3. #include "omani.h"
  4. #include "sysdefs.h"
  5.  
  6. struct fmtchunk {
  7.         char *fmt;
  8.         char  type;
  9. };
  10.  
  11. static struct fmtchunk *new_fmtchunk( int len )
  12. {
  13.         struct fmtchunk *res;
  14.  
  15.         res = (struct fmtchunk*)MALLOC( sizeof(*res) );
  16.         if ( !res ) return NULL;
  17.  
  18.         res->fmt = (char*)MALLOC( len );
  19.         res->type = '\0';
  20.         if ( !res->fmt ) {
  21.                 FREE( res );
  22.                 return NULL;
  23.         }
  24.  
  25.         return res;
  26. }
  27.  
  28. static void printf_sfree( struct fmtchunk **ptr )
  29. {
  30.         struct fmtchunk **c;
  31.  
  32.         if ( ptr ) {
  33.                 for ( c = ptr; *c; c++ ) {
  34.                         if ( (*c)->fmt ) FREE( (*c)->fmt );
  35.                         FREE( *c );
  36.                 }
  37.                 
  38.                 FREE( ptr );
  39.         }
  40. }
  41.  
  42. static struct fmtchunk **printf_split( const char *fmt )
  43. {
  44.         int n, i, state, begin, len;
  45.         const char *c;
  46.         struct fmtchunk **res;
  47.         struct fmtchunk **d;
  48.         
  49.         const char *convspec = "diouxXeEfFgGaAcspn%";
  50.         
  51.         if ( !fmt ) return NULL;
  52.         for ( n=0, c=fmt; *c; c++ ) 
  53.                 if ( *c == '%' ) n++;
  54.  
  55.         res = (struct fmtchunk **)CALLOC( n+2, sizeof( res[0] ));
  56.         if ( !res ) {
  57.                 fatal( "memory allocation error" );
  58.                 return NULL;
  59.         } 
  60.  
  61.         d = res;
  62.         state = begin = 0;
  63.         
  64.         for ( i=0, c=fmt; *c; c++, i++ ) {
  65.                 if ( state ) {
  66.                         if ( strchr( convspec, *c ) ) {
  67.                                 len = i-begin+1;
  68.                                 *d = new_fmtchunk( len + 1 );
  69.                                 
  70.                                 if ( !*d ) {
  71.                                         printf_sfree( res );
  72.                                         return NULL;
  73.                                 }
  74.  
  75.                                 memcpy( (*d)->fmt, fmt+begin, len );
  76.                                 (*d)->fmt[ len ] = '\0';
  77.                                 (*d)->type = *c;
  78.                                 d++;
  79.                                 begin = i+1;
  80.                                 state = 0;
  81.                         }
  82.                 }
  83.                 else {
  84.                         if ( *c == '%' ) state = 1;
  85.                 }
  86.         }
  87.  
  88.         if ( begin != i ) {
  89.                 len = i-begin+1;
  90.                 *d = new_fmtchunk( len + 1 );
  91.                 if ( !*d ) {
  92.                         printf_sfree( res );
  93.                         return NULL;
  94.                 }
  95.  
  96.                 memcpy( (*d)->fmt, fmt+begin, len );
  97.                 (*d)->fmt[ len ] = '\0';
  98.         }
  99.  
  100.         return res;
  101. }
  102.  
  103. int prn_get_int( int n )
  104. {
  105.         int type;
  106.  
  107.         type = ob_type( n );
  108.         switch( type ) {
  109.                 case 'f':
  110.                         return ob_getf( n );
  111.                 case 's':
  112.                         return atoi( ob_gets( n ) );
  113.                 default: 
  114.                         return ob_geti( n );
  115.         }
  116. }
  117.  
  118. unsigned prn_get_unsigned( int n )
  119. {
  120.         return (unsigned)prn_get_int( n ); 
  121. }
  122.  
  123. double prn_get_double( int n )
  124. {
  125.         int type;
  126.  
  127.         type = ob_type( n );
  128.         switch( type ) {
  129.                 case 'i':
  130.                         return ob_geti( n );
  131.                 case 's':
  132.                         return atof( ob_gets( n ) );
  133.                 default: 
  134.                         return ob_getf( n );
  135.         }
  136. }
  137.  
  138. const char *prn_get_string( int n )
  139. {
  140.         static char buf[ 128 ] = "";
  141.         
  142.         int type;
  143.  
  144.         type = ob_type( n );
  145.         switch( type ) {
  146.                 case 'i':
  147.                         snprintf( buf, sizeof(buf), "%d", ob_geti( n ));
  148.                         break;
  149.                 case 'f':
  150.                         snprintf( buf, sizeof(buf), "%f", ob_getf( n ));
  151.                         break;
  152.                 case 's':
  153.                         return ob_gets( n );
  154.         }
  155.         
  156.         return buf;
  157. }
  158.  
  159. int snprintfo( char *buf, int size, const char *fmt, int *data, int ndata )
  160. {
  161.         char *d;
  162.         int n, ndx, len;
  163.         struct fmtchunk **split;
  164.         struct fmtchunk **s;
  165.         
  166.         if ( buf ) buf[ 0 ] = '\0';
  167.         if (!( buf && fmt )) return 0;
  168.         split = printf_split( fmt );
  169.         if ( !split ) return 0;
  170.  
  171.         d = buf;
  172.         n = ndx = 0;
  173.  
  174.         for ( s=split; *s; s++ ) {
  175.                 switch( (*s)->type ) {
  176.                         case 'd':
  177.                         case 'i':
  178.                                 snprintf( d, size-n, (*s)->fmt,
  179.                                                 (ndata>0) ? 
  180.                                                 prn_get_int( data[ndx++] ): 0 );
  181.                                 break;
  182.                         case 'o':
  183.                         case 'u':
  184.                         case 'x':
  185.                         case 'X':
  186.                                 snprintf( d, size-n, (*s)->fmt,
  187.                                                 (ndata>0) ? 
  188.                                                 prn_get_unsigned( data[ndx++] ): 0 );
  189.                                 break;
  190.                         case 'e':
  191.                         case 'E':
  192.                         case 'f':
  193.                         case 'F':
  194.                         case 'g':
  195.                         case 'G':
  196.                         case 'a':
  197.                         case 'A':
  198.                                 snprintf( d, size-n, (*s)->fmt,
  199.                                                 (ndata>0) ? 
  200.                                                 prn_get_double( data[ndx++] ): 0 );
  201.                                 break;
  202.                         case 's':
  203.                                 snprintf( d, size-n, (*s)->fmt,
  204.                                                 (ndata>0) ? 
  205.                                                 prn_get_string( data[ndx++] ): 0 );
  206.                                 break;
  207.                         case 'c':
  208.                                 snprintf( d, size-n, (*s)->fmt,
  209.                                                 (ndata>0) ? 
  210.                                                 prn_get_string( data[ndx++] )[0]: 0 );
  211.                                 break;
  212.                         case '%':
  213.                                 snprintf( d, size-n, "%%" );
  214.                                 break;
  215.                         default:
  216.                                 snprintf( d, size-n, "%s", (*s)->fmt );
  217.                                 break;
  218.                                 
  219.  
  220.                 }
  221.  
  222.                 ndata--;
  223.  
  224.                 len = strlen( d );
  225.                 d += len;
  226.                 n += len;
  227.                 if ( n >= size ) break;
  228.         }
  229.        
  230.         printf_sfree( split );
  231.         return n;
  232. }
  233.  
  234.